package cn.njupt;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

//要知道接口都是提供给用户使用的，需要知道用户能提供哪些数据
public abstract class Graph<V,E> {
    protected WeightManager<E> weightManager;
    public Graph(){
    }
    public Graph(WeightManager<E> weightManager){
        this.weightManager=weightManager;
    }

    public abstract int edgesSize();

    public abstract int verticesSize();

    public abstract void addVertex(V value);

    public abstract void addEdge(V from,V to,E weight);

    public abstract void addEdge(V from,V to);

    public abstract void removeEdge(V from,V to);

    public abstract void removeVertex(V value);

    public abstract void bfs(V v,Visitor<V> visitor);

    public abstract void dfs(V v);

    public abstract List<V> topologicalSort();

    public abstract Set<EdgeInfo<V,E>> mst();

    public abstract Map<V, PathInfo<V, E>> shortestPath(V begin);

    public interface WeightManager<E>{
        int compare(E e1,E e2 );

        E add(E w1,E w2);
    }

    public static class PathInfo<V,E>{
        private E weight;
        private LinkedList<EdgeInfo<V,E>> list =new LinkedList<>();;
        public PathInfo(E weight){
           this.weight=weight;
        }

        public E getWeight() {
            return weight;
        }

        public void setWeight(E weight) {
            this.weight = weight;
        }

        public LinkedList<EdgeInfo<V, E>> getList() {
            return list;
        }

        public void setList(LinkedList<EdgeInfo<V, E>> list) {
            this.list = list;
        }

        @Override
        public String toString() {
            return "PathInfo{" +
                    "weight=" + weight +
                    ", list=" + list +
                    '}';
        }
    }

    public  static class EdgeInfo<V,E>{
        private V from;
        private V to;
        private E weight;
        public EdgeInfo(V from,V to,E weight){
            this.from=from;
            this.to=to;
            this.weight=weight;
        }

        @Override
        public String toString() {
            return "EdgeInfo{" +
                    "from=" + from +
                    ", to=" + to +
                    ", weight=" + weight +
                    '}';
        }

        public V getFrom() {
            return from;
        }

        public void setFrom(V from) {
            this.from = from;
        }

        public V getTo() {
            return to;
        }

        public void setTo(V to) {
            this.to = to;
        }

        public E getWeight() {
            return weight;
        }

        public void setWeight(E weight) {
            this.weight = weight;
        }
    }

    public interface Visitor<V>{
        public abstract boolean visit(V v);
    }
}
